using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using HamsterDocs.Domains.Users;

namespace HamsterDocs.Hosting.Services;

public static class SeedService
{
    public static async Task EnsureAdminAsync(
        HamsterDocs.EntityFrameworkCore.IContext context,
        IConfiguration configuration,
        ILogger logger,
        IHostEnvironment env)
    {
        if (!env.IsDevelopment())
        {
            return;
        }

        var db = (DbContext)context;

        var email = configuration.GetSection("Seed")["AdminEmail"] ?? "root@local";
        var userName = configuration.GetSection("Seed")["AdminUserName"] ?? "root";
        var password = configuration.GetSection("Seed")["AdminPassword"] ?? "Aa123456";

        var exists = await db.Set<User>()
            .AsNoTracking()
            .AnyAsync(u => u.Email == email || (u.Role != null && u.Role == "Admin"));

        if (exists)
        {
            return;
        }

        var salt = CreateSalt();
        var hash = HashPassword(password, salt);

        var user = new User
        {
            UserName = userName,
            Email = email,
            Role = "Admin",
            PasswordSalt = salt,
            PasswordHash = hash,
            IsActive = true,
            CreatedAt = DateTime.UtcNow,
            UpdatedAt = DateTime.UtcNow
        };

        db.Set<User>().Add(user);
        await db.SaveChangesAsync();

        logger.LogInformation("Seeded admin user {Email}", email);
    }

    private static string CreateSalt(int length = 16)
    {
        var bytes = new byte[length];
        System.Security.Cryptography.RandomNumberGenerator.Fill(bytes);
        return Convert.ToBase64String(bytes);
    }

    private static string HashPassword(string password, string salt, int iterations = 100000, int length = 32)
    {
        var saltBytes = Convert.FromBase64String(salt);
        using var pbkdf2 = new System.Security.Cryptography.Rfc2898DeriveBytes(password, saltBytes, iterations, System.Security.Cryptography.HashAlgorithmName.SHA256);
        var bytes = pbkdf2.GetBytes(length);
        return Convert.ToBase64String(bytes);
    }
}